package cn.tedu.charging.order.config;

import cn.tedu.charging.order.mqtt.MqttConsumer;
import cn.tedu.charging.order.mqtt.MqttContext;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 连接消息中间件 EMQX的 配置类
 * 连接EMQX的目的 是为了 和 设备通信
 * 能给设备发消息
 * 能接收设备发来的消息
 */
@Configuration
public class MqttConfiguration {

    private static final Logger log = LoggerFactory.getLogger(MqttConfiguration.class);

    /**
     * 连接地址 tcp 协议 1883 端口号
     * 配置信息 应该 放到配置文件 或者放到 配置中心 nacos
     */
    private String host = "tcp://127.0.0.1:1883";

    /**
     * 用户名
     * 配置信息 应该 放到配置文件 或者放到 配置中心 nacos
     */
    private String userName = "admin";

    /**
     * 密码
     * 配置信息 应该 放到配置文件 或者放到 配置中心 nacos
     */
    private String password = "public";

    /**
     * 客户端ID
     * 相同的id EMQX 不允许同时连接 不能同时在线
     * 为了让多个订单服务 同时能连接上EMQX ，
     * 给每个订单服务都分配一个不同的客户端ID 用随机数来实现
     */
    private String clientId = "order_service_client" + Math.random();

    /**
     * 通过  @Bean 注解，创建 MqttClient 对象并且交给spring容器管理
     * 别的 在容器中的类 可以通过注入的方式 使用 MqttClient
     * @return
     */
    @Bean
    public MqttClient mqttClient(MqttContext mqttContext) throws Exception{
        //通过 连接地址 和 客户端id创建 MqttClient 对象
        MqttClient mqttClient = new MqttClient(host, clientId);
        // 创建 MqttConnectOptions 连接相关的配置
        MqttConnectOptions options = new MqttConnectOptions();
        //配置用户名
        options.setUserName(userName);
        //配置密码 char[] 字符串转成字符数组 password.toCharArray()
        // 把 字符串 转换为 字符数组
        //字符串常用的方法 大家得关注 String
        options.setPassword(password.toCharArray());

        //options 有很多其他的配置 可以自己了解
    /*  options.setCleanSession(true);
        options.setKeepAliveInterval(60);
        options.setConnectionTimeout(30);
        options.setMaxInflight(100);
        options.setAutomaticReconnect(true);
        options.setExecutorServiceTimeout(1000);
  */

        MqttConsumer mqttConsumer = new MqttConsumer(mqttClient, mqttContext);
        mqttClient.setCallback(mqttConsumer);
        // 通过配置和EMQX进行连接
        mqttClient.connect(options);//只管发出消息，不管是否连接成功都继续执行后面的代码，外面的连接需要时间，所以回调不会立即得到结果，等待连接成功时再返回结果
        log.debug("mqttClient.connect mqtt客户端试图和EMQX连接，是否连接成功不知道，连接成功的结果" +
                "是通过 Callback 回调，连接结果来调用callback里的方法 connectComplete");

        return mqttClient;
    }

}
